import axios from 'axios'
import { Message } from '@arco-design/web-vue'
import tool from '@/utils/tool'
import { get, isEmpty } from 'lodash'
import qs from 'qs'
import { h } from 'vue'
import { IconFaceFrownFill } from '@arco-design/web-vue/dist/arco-vue-icon'
import router from '@/router'

function createService() {
  // 創建一個 axios 實例
  const service = axios.create()

  // HTTP request 攔截器
  service.interceptors.request.use(
    (config) => config,
    (error) => {
      // 失敗
      return Promise.reject(error)
    }
  )

  // HTTP response 攔截器
  service.interceptors.response.use(
    (response) => {
      if (
        response.status === 200 &&
        response.request.responseURL.includes('export')
      ) {
        return response.data
      }
      if (response.status === 200) {
        if (response.data.code != 0) {
          if (
            response.data.code === 1002 ||
            response.data.code === 1004 ||
            response.data.code === 1005
          ) {
            Message.error({
              content: response.data.message || response.data.msg,
              icon: () => h(IconFaceFrownFill)
            })
            tool.cookie.remove('Authorization')
            router.push({ name: 'login' })
          } else {
            Message.error({
              content: response.data.message || response.data.msg,
              icon: () => h(IconFaceFrownFill)
            })
          }
          return Promise.reject(response.data)
        } else {
          return Promise.resolve(response.data)
        }
      } else {
        return Promise.resolve(response.data)
      }
    },
    (error) => {
      const err = (text) => {
        Message.error({
          content:
            error.response && error.response.data && error.response.data.message
              ? error.response.data.message
              : text,
          icon: () => h(IconFaceFrownFill)
        })
      }
      if (error.response && error.response.data) {
        switch (error.response.status) {
          case 404:
            err('服務器資源不存在')
            break
          case 500:
            err('服務器內部錯誤')
            break
          case 401:
            throttle(() => {
              err('登入狀態已過期，需要重新登入')
              tool.cookie.remove('Authorization')
              router.push({ path: '/login' })
            })()
            break
          case 403:
            err('沒有權限訪問該資源')
            break
          default:
            err('未知錯誤！')
        }
      } else {
        err('請求超時，服務器無響應！')
      }
      return Promise.reject({
        code: error.response.status || 500,
        message: error.response.statusText || '未知錯誤'
      })
    }
  )
  return service
}

//節流
function throttle(fn, wait = 1500) {
  return function () {
    let context = this
    if (!throttle.timer) {
      fn.apply(context, arguments)
      throttle.timer = setTimeout(function () {
        throttle.timer = null
      }, wait)
    }
  }
}

function stringify(data) {
  return qs.stringify(data, { allowDots: true, encode: false })
}

function formatToken(token) {
  return token ? `Authorization=${token}` : null
}

/**
 * @description 創建請求方法
 * @param service
 */
function createRequest(service) {
  return function (config) {
    let obj = {}
    if (config.url.includes('export')) {
      obj.responseType = 'blob'
    }
    const env = import.meta.env
    const configDefault = {
      headers: Object.assign(
        {
          'Content-Type': get(
            config,
            'headers.Content-Type',
            'application/json;charset=UTF-8'
          )
        },
        config.headers
      ),
      ...obj,
      timeout: 60000,
      data: {},
      withCredentials: true
    }
    delete config.headers
    // return
    const option = Object.assign(configDefault, config)

    // json
    if (!isEmpty(option.params)) {
      option.url = option.url + '?' + stringify(option.params)
      option.params = {}
    }
    if (env.VITE_APP_OPEN_PROXY === 'true') {
      option.baseURL = env.VITE_APP_PROXY_PREFIX
    } else {
      option.baseURL = env.VITE_APP_BASE_URL
    }
    return service(option)
  }
}

export const service = createService()
export const request = createRequest(service)
